/**************************************************************************
 * arch/z80/src/z8/z8_xdef.S
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.  The
 * ASF licenses this file to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the
 * License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 *
 **************************************************************************/

/**************************************************************************
 * Included Files
 **************************************************************************/

#include <nuttx/config.h>
#include <arch/irq.h>

#include <ez8.inc>
#include <vect.inc>

/**************************************************************************
 * Pre-processor Definitions
 **************************************************************************/

/**************************************************************************
 * External References / External Definitions
 **************************************************************************/

	xref	_z80_doirq:ROM

#if defined(ENCORE_VECTORS)
	xdef	_z8_wdt_handler
	xdef	_z8_trap_handler
if EZ8_TIMER3=1
	xdef	_z8_timer2_handler
endif
	xdef	_z8_timer1_handler
	xdef	_z8_timer0_handler
if EZ8_UART0=1
	xdef	_z8_uart0rx_handler
	xdef	_z8_uart0tx_handler
endif
if EZ8_I2C=1
	xdef	_z8_i2c_handler
endif
if EZ8_SPI=1
	xdef	_z8_spi_handler
endif
if EZ8_ADC=1
	xdef	_z8_adc_handler
endif
	xdef	_z8_p7ad_handler
	xdef	_z8_p6ad_handler
 	xdef	_z8_p5ad_handler
	xdef	_z8_p4ad_handler
	xdef	_z8_p3ad_handler
	xdef	_z8_p2ad_handler
	xdef	_z8_p1ad_handler
	xdef	_z8_p0ad_handler
if EZ8_TIMER4=1
	xdef	_z8_timer3_handler
endif
if EZ8_UART1=1
	xdef	_z8_uart1rx_handler
	xdef	_z8_uart1tx_handler
endif
if EZ8_DMA=1
	xdef	_z8_dma_handler
endif
if EZ8_PORT1=0
	xdef	_z8_c3_handler
	xdef	_z8_c2_handler
	xdef	_z8_c1_handler
	xdef	_z8_c0_handler
endif

/**************************************************************************/

#elif defined(ENCORE_XP_VECTORS)

	xdef _z8_wdt_handler
	xdef _z8_trap_handler
if EZ8_TIMER3=1
	xdef _z8_timer2_handler
endif
	xdef _z8_timer1_handler
	xdef _z8_timer0_handler
if EZ8_UART0=1
	xdef _z8_uart0rx_handler
	xdef _z8_uart0tx_handler
endif
if EZ8_I2C=1
	xdef _z8_i2c_handler
endif
if EZ8_SPI=1
	xdef _z8_spi_handler
endif
if (EZ8_ADC=1) || (EZ8_ADC_NEW=1)
	xdef _z8_adc_handler
endif
	xdef _z8_p7ad_handler
	xdef _z8_p6ad_handler
 	xdef _z8_p5ad_handler
	xdef _z8_p4ad_handler
	xdef _z8_p3ad_handler
	xdef _z8_p2ad_handler
	xdef _z8_p1ad_handler
	xdef _z8_p0ad_handler
if EZ8_TIMER4=1
	xdef _z8_timer3_handler
endif
if EZ8_UART1=1
	xdef _z8_uart1rx_handler
	xdef _z8_uart1tx_handler
endif
if EZ8_DMA=1
	xdef _z8_dma_handler
endif
if (EZ8_PORT1=0)
	xdef _z8_c3_handler
	xdef _z8_c2_handler
	xdef _z8_c1_handler
	xdef _z8_c0_handler
endif
	xdef _z8_potrap_handler
	xdef _z8_wotrap_handler

/**************************************************************************/

#elif defined(ENCORE_XP16K_VECTORS)

	xdef _z8_wdt_handler
	xdef _z8_trap_handler
if EZ8_TIMER3=1
	xdef _z8_timer2_handler
endif
	xdef _z8_timer1_handler
	xdef _z8_timer0_handler
if EZ8_UART0=1
	xdef _z8_uart0rx_handler
	xdef _z8_uart0tx_handler
endif
if EZ8_I2C=1
	xdef _z8_i2c_handler
endif
if EZ8_ESPI=1
	xdef _z8_spi_handler
endif
if EZ8_ADC_NEW=1
	xdef _z8_adc_handler
endif
	xdef _z8_p7ad_handler
	xdef _z8_p6ad_handler
 	xdef _z8_p5ad_handler
	xdef _z8_p4ad_handler
	xdef _z8_p3ad_handler
	xdef _z8_p2ad_handler
	xdef _z8_p1ad_handler
	xdef _z8_p0ad_handler
if EZ8_MCT=1
	xdef _z8_mct_handler
endif
if EZ8_UART1=1
	xdef _z8_uart1rx_handler
	xdef _z8_uart1tx_handler
endif
	xdef _z8_c3_handler
	xdef _z8_c2_handler
	xdef _z8_c1_handler
	xdef _z8_c0_handler
	xdef _z8_potrap_handler
	xdef _z8_wotrap_handler

/**************************************************************************/

#elif defined(ENCORE_MC_VECTORS)

	xdef _z8_wdt_handler
	xdef _z8_trap_handler
	xdef _z8_pwmtimer_handler
	xdef _z8_pwmfault_handler
if EZ8_ADC_NEW=1
	xdef _z8_adc_handler
endif
	xdef _z8_cmp_handler
	xdef _z8_timer0_handler
if EZ8_UART0
	xdef _z8_uart0rx_handler
	xdef _z8_uart0tx_handler
endif
if EZ8_SPI=1
	xdef _z8_spi_handler
endif
if EZ8_I2C=1
	xdef _z8_i2c_handler
endif
	xdef _z8_c0_handler
	xdef _z8_pb_handler
	xdef _z8_p7ap3a_handler
	xdef _z8_p6ap2a_handler
	xdef _z8_p5ap1a_handler
	xdef _z8_p4ap0a_handler
	xdef _z8_potrap_handler
	xdef _z8_wotrap_handler
#endif

/**************************************************************************
 * Macros
 **************************************************************************/

ENTER :	MACRO	val
	pushx	rp			/* Save the current RP value in the stack */
	srp	#%f0			/* Load the interrupt register pointer */
	ld	r0, #val		/* Pass the new value in r0 */
	jr	_z8_common_handler	/* The rest of the handling is common */
	ENDMAC	ENTER

LEAVE :	MACRO
	popx	rp			/* Restore the user register pointer */
	iret				/* And return from interrupt */
	ENDMAC	LEAVE

/**************************************************************************
 * Code
 **************************************************************************/

	segment CODE

/**************************************************************************
 * Interrupt Vectors
 **************************************************************************/

#if defined(ENCORE_VECTORS)
	vector WDT	= _z8_wdt_handler
	vector TRAP	= _z8_trap_handler
if EZ8_TIMER3=1
	vector TIMER2	= _z8_timer2_handler
endif
	vector TIMER1	= _z8_timer1_handler
	vector TIMER0	= _z8_timer0_handler
if EZ8_UART0=1
	vector UART0_RX	= _z8_uart0rx_handler
	vector UART0_TX	= _z8_uart0tx_handler
endif
if EZ8_I2C=1
	vector I2C	= _z8_i2c_handler
endif
if EZ8_SPI=1
	vector SPI	= _z8_spi_handler
endif
if EZ8_ADC=1
	vector ADC	= _z8_adc_handler
endif
	vector P7AD	= _z8_p7ad_handler
	vector P6AD	= _z8_p6ad_handler
 	vector P5AD	= _z8_p5ad_handler
	vector P4AD	= _z8_p4ad_handler
	vector P3AD	= _z8_p3ad_handler
	vector P2AD	= _z8_p2ad_handler
	vector P1AD	= _z8_p1ad_handler
	vector P0AD	= _z8_p0ad_handler
if EZ8_TIMER4=1
	vector TIMER3	= _z8_timer3_handler
endif
if EZ8_UART1=1
	vector UART1_RX	= _z8_uart1rx_handler
	vector UART1_TX	= _z8_uart1tx_handler
endif
if EZ8_DMA=1
	vector DMA	= _z8_dma_handler
endif
if EZ8_PORT1=0
	vector C3	= _z8_c3_handler
	vector C2	= _z8_c2_handler
	vector C1	= _z8_c1_handler
	vector C0	= _z8_c0_handler
endif

/**************************************************************************/

#elif defined(ENCORE_XP_VECTORS)

	vector WDT	= _z8_wdt_handler
	vector TRAP	= _z8_trap_handler
if EZ8_TIMER3=1
	vector TIMER2	= _z8_timer2_handler
endif
	vector TIMER1	= _z8_timer1_handler
	vector TIMER0	= _z8_timer0_handler
if EZ8_UART0=1
	vector UART0_RX	= _z8_uart0rx_handler
	vector UART0_TX	= _z8_uart0tx_handler
endif
if EZ8_I2C=1
	vector I2C	= _z8_i2c_handler
endif
if EZ8_SPI=1
	vector SPI	= _z8_spi_handler
endif
if (EZ8_ADC=1) || (EZ8_ADC_NEW=1)
	vector ADC	= _z8_adc_handler
endif
	vector P7AD	= _z8_p7ad_handler
	vector P6AD	= _z8_p6ad_handler
 	vector P5AD	= _z8_p5ad_handler
	vector P4AD	= _z8_p4ad_handler
	vector P3AD	= _z8_p3ad_handler
	vector P2AD	= _z8_p2ad_handler
	vector P1AD	= _z8_p1ad_handler
	vector P0AD	= _z8_p0ad_handler
if EZ8_TIMER4=1
	vector TIMER3	= _z8_timer3_handler
endif
if EZ8_UART1=1
	vector UART1_RX	= _z8_uart1rx_handler
	vector UART1_TX	= _z8_uart1tx_handler
endif
if EZ8_DMA=1
	vector DMA	= _z8_dma_handler
endif
if EZ8_PORT1=0
	vector C3	= _z8_c3_handler
	vector C2	= _z8_c2_handler
	vector C1	= _z8_c1_handler
	vector C0	= _z8_c0_handler
endif
	vector POTRAP	= _z8_potrap_handler
	vector WOTRAP	= _z8_wotrap_handler

/**************************************************************************/

#elif defined(ENCORE_XP16K_VECTORS)

	vector WDT	= _z8_wdt_handler
	vector TRAP	= _z8_trap_handler
if EZ8_TIMER3=1
	vector TIMER2	= _z8_timer2_handler
endif
	vector TIMER1	= _z8_timer1_handler
	vector TIMER0	= _z8_timer0_handler
if EZ8_UART0=1
	vector UART0_RX	= _z8_uart0rx_handler
	vector UART0_TX	= _z8_uart0tx_handler
endif
if EZ8_I2C=1
	vector I2C	= _z8_i2c_handler
endif
if EZ8_ESPI=1
	vector SPI	= _z8_spi_handler
endif
if EZ8_ADC_NEW=1
	vector ADC	= _z8_adc_handler
endif
	vector P7AD	= _z8_p7ad_handler
	vector P6AD	= _z8_p6ad_handler
 	vector P5AD	= _z8_p5ad_handler
	vector P4AD	= _z8_p4ad_handler
	vector P3AD	= _z8_p3ad_handler
	vector P2AD	= _z8_p2ad_handler
	vector P1AD	= _z8_p1ad_handler
	vector P0AD	= _z8_p0ad_handler
if EZ8_MCT=1
	vector MCT	= _z8_mct_handler
endif
if EZ8_UART1=1
	vector UART1_RX	= _z8_uart1rx_handler
	vector UART1_TX	= _z8_uart1tx_handler
endif
	vector C3	= _z8_c3_handler
	vector C2	= _z8_c2_handler
	vector C1	= _z8_c1_handler
	vector C0	= _z8_c0_handler
	vector POTRAP	= _z8_potrap_handler
	vector WOTRAP	= _z8_wotrap_handler

/**************************************************************************/

#elif defined(ENCORE_MC_VECTORS)

	vector WDT	= _z8_wdt_handler
	vector TRAP	= _z8_trap_handler
	vector PWMTIMER	= _z8_pwmtimer_handler
	vector PWMFAULT	= _z8_pwmfault_handler
if EZ8_ADC_NEW=1
	vector ADC	= _z8_adc_handler
endif
	vector CMP	= _z8_cmp_handler
	vector TIMER0	= _z8_timer0_handler
if EZ8_UART0
	vector UART0_RX	= _z8_uart0rx_handler
	vector UART0_TX	= _z8_uart0tx_handler
endif
if EZ8_SPI=1
	vector SPI	= _z8_spi_handler
endif
if EZ8_I2C=1
	vector I2C	= _z8_i2c_handler
endif
	vector C0	= _z8_c0_handler
	vector PB	= _z8_pb_handler
	vector P7A	= _z8_p7ap3a_handler
	vector P6A	= _z8_p6ap2a_handler
	vector P5A	= _z8_p5ap1a_handler
	vector P4A	= _z8_p4ap0a_handler
	vector POTRAP	= _z8_potrap_handler
	vector WOTRAP	= _z8_wotrap_handler
#endif

/**************************************************************************
 * Name: _z16f_*_handler
 *
 * Description:
 *   Map individual interrupts into interrupt number and branch to common
 *   interrupt handling logic.  If higher interrupt handling performance
 *   for particular interrupts is required, then those interrupts should
 *   be picked off here and handled outside of the common logic.
 *
 *   On entry to any of these handlers, the stack contains the following:
 *
 *         TOS before interrupt
 *         PC[7:0]
 *         PC[15:8]
 *   SP -> Flags Register
 *
 **************************************************************************/

#if defined(ENCORE_VECTORS)
_z8_wdt_handler:
	ENTER(Z8_WDT_IRQ)
_z8_trap_handler:
	ENTER(Z8_TRAP_IRQ)
if EZ8_TIMER3=1
_z8_timer2_handler:
	ENTER(Z8_TIMER2_IRQ)
endif
_z8_timer1_handler:
	ENTER(Z8_TIMER1_IRQ)
_z8_timer0_handler:
	ENTER(Z8_TIMER0_IRQ)
if EZ8_UART0=1
_z8_uart0rx_handler:
	ENTER(Z8_UART0_RX_IRQ)
_z8_uart0tx_handler:
	ENTER(Z8_UART0_TX_IRQ)
endif
if EZ8_I2C=1
_z8_i2c_handler:
	ENTER(Z8_I2C_IRQ)
endif
if EZ8_SPI=1
_z8_spi_handler:
	ENTER(Z8_SPI_IRQ)
endif
if EZ8_ADC=1
_z8_adc_handler:
	ENTER(Z8_ADC_IRQ)
endif
_z8_p7ad_handler:
	ENTER(Z8_P7AD_IRQ)
_z8_p6ad_handler:
	ENTER(Z8_P6AD_IRQ)
_z8_p5ad_handler:
	ENTER(Z8_P5AD_IRQ)
_z8_p4ad_handler:
	ENTER(Z8_P4AD_IRQ)
_z8_p3ad_handler:
	ENTER(Z8_P3AD_IRQ)
_z8_p2ad_handler:
	ENTER(Z8_P2AD_IRQ)
_z8_p1ad_handler:
	ENTER(Z8_P1AD_IRQ)
_z8_p0ad_handler:
	ENTER(Z8_P0AD_IRQ)
if EZ8_TIMER4=1
_z8_timer3_handler:
	ENTER(Z8_TIMER3_IRQ)
endif
if EZ8_UART1=1
_z8_uart1rx_handler:
	ENTER(Z8_UART1_RX_IRQ)
_z8_uart1tx_handler:
	ENTER(Z8_UART1_TX_IRQ)
endif
if EZ8_DMA=1
_z8_dma_handler:
	ENTER(Z8_DMA_IRQ)
endif
if EZ8_PORT1=0
_z8_c3_handler:
	ENTER(Z8_C3_IRQ)
_z8_c2_handler:
	ENTER(Z8_C2_IRQ)
_z8_c1_handler:
	ENTER(Z8_C1_IRQ)
_z8_c0_handler:
	ENTER(Z8_C0_IRQ)
endif

/**************************************************************************/

#elif defined(ENCORE_XP_VECTORS)

_z8_wdt_handler:
	ENTER(Z8_WDT_IRQ)
_z8_trap_handler:
	ENTER(Z8_TRAP_IRQ)
if EZ8_TIMER3=1
_z8_timer2_handler:
	ENTER(Z8_TIMER2_IRQ)
endif
_z8_timer1_handler:
	ENTER(Z8_TIMER1_IRQ)
_z8_timer0_handler:
	ENTER(Z8_TIMER0_IRQ)
if EZ8_UART0=1
_z8_uart0rx_handler:
	ENTER(Z8_UART0_RX_IRQ)
_z8_uart0tx_handler:
	ENTER(Z8_UART0_TX_IRQ)
endif
if EZ8_I2C=1
_z8_i2c_handler:
	ENTER(Z8_I2C_IRQ)
endif
if EZ8_SPI=1
_z8_spi_handler:
	ENTER(Z8_SPI_IRQ)
endif
if (EZ8_ADC=1) || (EZ8_ADC_NEW=1)
_z8_adc_handler:
	ENTER(Z8_ADC_IRQ)
endif
_z8_p7ad_handler:
	ENTER(Z8_P7AD_IRQ)
_z8_p6ad_handler:
	ENTER(Z8_P6AD_IRQ)
_z8_p5ad_handler:
	ENTER(Z8_P5AD_IRQ)
_z8_p4ad_handler:
	ENTER(Z8_P4AD_IRQ)
_z8_p3ad_handler:
	ENTER(Z8_P3AD_IRQ)
_z8_p2ad_handler:
	ENTER(Z8_P2AD_IRQ)
_z8_p1ad_handler:
	ENTER(Z8_P1AD_IRQ)
_z8_p0ad_handler:
	ENTER(Z8_P0AD_IRQ)
if EZ8_TIMER4=1
_z8_timer3_handler:
	ENTER(Z8_TIMER3_IRQ)
endif
if EZ8_UART1=1
_z8_uart1rx_handler:
	ENTER(Z8_UART1_RX_IRQ)
_z8_uart1tx_handler:
	ENTER(Z8_UART1_TX_IRQ)
endif
if EZ8_DMA=1
_z8_dma_handler:
	ENTER(Z8_DMA_IRQ)
endif
if EZ8_PORT1=0
_z8_c3_handler:
	ENTER(Z8_C3_IRQ)
_z8_c2_handler:
	ENTER(Z8_C2_IRQ)
_z8_c1_handler:
	ENTER(Z8_C1_IRQ)
_z8_c0_handler:
	ENTER(Z8_C0_IRQ)
endif
_z8_potrap_handler:
	ENTER(Z8_POTRAP_IRQ)
_z8_wotrap_handler:
	ENTER(Z8_WOTRAP_IRQ)

/**************************************************************************/

#elif defined(ENCORE_XP16K_VECTORS)

_z8_wdt_handler:
	ENTER(Z8_WDT_IRQ)
_z8_trap_handler:
	ENTER(Z8_TRAP_IRQ)
if EZ8_TIMER3=1
_z8_timer2_handler:
	ENTER(Z8_TIMER2_IRQ)
endif
_z8_timer1_handler:
	ENTER(Z8_TIMER1_IRQ)
_z8_timer0_handler:
	ENTER(Z8_TIMER0_IRQ)
if EZ8_UART0=1
_z8_uart0rx_handler:
	ENTER(Z8_UART0_RX_IRQ)
_z8_uart0tx_handler:
	ENTER(Z8_UART0_TX_IRQ)
endif
if EZ8_I2C=1
_z8_i2c_handler:
	ENTER(Z8_I2C_IRQ)
endif
if EZ8_ESPI=1
_z8_spi_handler:
	ENTER(Z8_SPI_IRQ)
endif
if EZ8_ADC_NEW=1
_z8_adc_handler:
	ENTER(Z8_ADC_IRQ)
endif
_z8_p7ad_handler:
	ENTER(Z8_P7AD_IRQ)
_z8_p6ad_handler:
	ENTER(Z8_P6AD_IRQ)
_z8_p5ad_handler:
	ENTER(Z8_P5AD_IRQ)
_z8_p4ad_handler:
	ENTER(Z8_P4AD_IRQ)
_z8_p3ad_handler:
	ENTER(Z8_P3AD_IRQ)
_z8_p2ad_handler:
	ENTER(Z8_P2AD_IRQ)
_z8_p1ad_handler:
	ENTER(Z8_P1AD_IRQ)
_z8_p0ad_handler:
	ENTER(Z8_P0AD_IRQ)
if EZ8_MCT=1
_z8_mct_handler:
	ENTER(Z8_MCT_IRQ)
endif
if EZ8_UART1=1
_z8_uart1rx_handler:
	ENTER(Z8_UART1_RX_IRQ)
_z8_uart1tx_handler:
	ENTER(Z8_UART1_TX_IRQ)
endif
_z8_c3_handler:
	ENTER(Z8_C3_IRQ)
_z8_c2_handler:
	ENTER(Z8_C2_IRQ)
_z8_c1_handler:
	ENTER(Z8_C1_IRQ)
_z8_c0_handler:
	ENTER(Z8_C0_IRQ)
_z8_potrap_handler:
	ENTER(Z8_POTRAP_IRQ)
_z8_wotrap_handler:
	ENTER(Z8_WOTRAP_IRQ)

/**************************************************************************/

#elif defined(ENCORE_MC_VECTORS)

_z8_wdt_handler:
	ENTER(Z8_WDT_IRQ)
_z8_trap_handler:
	ENTER(Z8_TRAP_IRQ)
_z8_pwmtimer_handler:
	ENTER(Z8_PWMTIMER_IRQ)
_z8_pwmfault_handler:
	ENTER(Z8_PWMFAULT_IRQ)
if EZ8_ADC_NEW=1
_z8_adc_handler:
	ENTER(Z8_ADC_IRQ)
endif
_z8_cmp_handler:
	ENTER(Z8_CMP_IRQ)
_z8_timer0_handler:
	ENTER(Z8_TIMER0_IRQ)
if EZ8_UART0
_z8_uart0rx_handler:
	ENTER(Z8_UART0_RX_IRQ)
_z8_uart0tx_handler:
	ENTER(Z8_UART0_TX_IRQ)
endif
if EZ8_SPI=1
_z8_spi_handler:
	ENTER(Z8_SPI_IRQ)
endif
if EZ8_I2C=1
_z8_i2c_handler:
	ENTER(Z8_I2C_IRQ)
endif
_z8_c0_handler:
	ENTER(Z8_C0_IRQ)
_z8_pb_handler:
	ENTER(Z8_PB_IRQ)
_z8_p7ap3a_handler:
	ENTER(Z8_P7A_IRQ)
_z8_p6ap2a_handler:
	ENTER(Z8_P6AP2A_IRQ)
_z8_p5ap1a_handler:
	ENTER(Z8_P5AP1A_IRQ)
_z8_p4ap0a_handler:
	ENTER(Z8_P4AP0A_IRQ)
_z8_potrap_handler:
	ENTER(Z8_POTRAP_IRQ)
_z8_wotrap_handler:
	ENTER(Z8_WOTRAP_IRQ)
#endif

/**************************************************************************
 * Name: _z16f_common_handler
 *
 * Description:
 *   Common IRQ handling logic
 *
 *   On entry, the stack contains the following:
 *
 *         TOS before interrupt
 *         PC[7:0]
 *         PC[15:8]
 *         Flags Register
 *   SP -> RP
 *
 *   R0 holds the IRQ number and the RP has been reset to %f0
 *
 **************************************************************************/

_z8_common_handler:
	/* Pass the address of the IRQ stack frame */

	ldx	r2, sph			/* rr2 = stack pointer */
	ldx	r3, spl
	push	r3			/* Pass as a parameter */
	push	r2

	/* Pass the IRQ number */

	push	r0

	/* Process the interrupt */

	call	_z80_doirq		/* Call the IRQ handler */

	/* Release arguments from the stack */

	pop	r4			/* Discard the IRQ argument */
	pop	r2			/* Recover the stack pointer parameter */
	pop	r3

	/* If a interrupt level context switch occurred, then the
	 * return value will be the same as the input value
	 */

	cp	r0, r2			/* Same as the return value? */
	jr	nz, _z8_switch
	cp	r1, r3
	jr	z, _z8_noswitch

	/* A context switch occurs.  Restore the use context.
	 * rr0 = pointer to context structgure.
	 */

_z8_switch:

	/* Destroy the interrupt return information on the stack */

	pop	r4			/* Destroy saved RP */
	pop	r4			/* Destroy saved flags */
	pop	r4			/* Destroy saved return address */
	pop	r4

	/* Copy all registers into the user register area. */

	clr	r2			/* rr2 = destination address */
	ldx	r3, XCPT_RP_OFFS(rr0)
	ld	r4, r0			/* rr4 = source address */
	ld	r5, r1
	ld	r6, #16			/* r6 = number of bytes to copy */

_z8_restore:
	ldx	r7, @rr4
	ldx	@rr2, r7
	incw	rr2
	incw	rr4
	djnz	r6, _z8_restore

	/* Set the new stack pointer */

	ldx	r2, XCPT_SPH_OFFS(rr0)
	ldx	r3, XCPT_SPL_OFFS(rr0)
	ldx	sph, r2
	ldx	spl, r3

	/* Push the return address onto the stack */

	ldx	r2, XCPT_PCH_OFFS(rr0)
	ldx	r3, XCPT_PCL_OFFS(rr0)
	push	r3
	push	r2

	/* Recover the flags and RP settings.. but don't restore them yet */

	ldx	r3, XCPT_FLAGS_OFFS(rr0)
	ldx	r4, XCPT_RP_OFFS(rr0)

	/* Determine whether interrupts must be enabled on return.  This
	 * would be nicer to do below, but later we will need to preserve
	 * the condition codes in the flags.
	 */

	ldx	r2, XCPT_IRQCTL_OFFS(rr0)
	tm	r2, #%80
	jr	nz, _z8_returnenabled

	/* Restore the flag settings */

	ldx	flags, r3

	/* Restore the user register page and return with interrupts disabled.
	 * Note that we cannot use the iret instruction because it unconditionally
	 * re-enabled interrupts
	 */

	ldx	rp, r4				/* Does not effect flags */
	ret					/* Does not effect flags */

_z8_returnenabled:
	/* Restore the flag settings */

	ldx	flags, r1

	/* Restore the user register page, re-enable interrupts and return.
	 * Note that we cannot use the iret instruction because it unconditionally
	 * re-enabled interrupts
	 */

	ldx	rp, r4				/* Does not effect flags */
	ei					/* Does not effect flags */
	ret					/* Does not effect flags */

_z8_noswitch:
	LEAVE

/**************************************************************************
 * Data
 **************************************************************************/

	/* Set aside area for interrupt registers */

	define interruptreg, space=rdata, org=%f0
	segment interruptreg
	ds  %10

	end	_z8_common_handler
